home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / LAPB.C < prev    next >
C/C++ Source or Header  |  1989-09-07  |  16KB  |  673 lines

  1. /* Link Access Procedures Balanced (LAPB) - with changes for rational
  2.  * behavior over packet radio
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9. #include "ip.h"
  10. #include "netrom.h"
  11.  
  12. static void handleit __ARGS((struct ax25_cb *axp,char pid,struct mbuf *bp));
  13. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  14. static int ackours __ARGS((struct ax25_cb *axp,char n));
  15. static void clr_ex __ARGS((struct ax25_cb *axp));
  16. static void enq_resp __ARGS((struct ax25_cb *axp));
  17. static void inv_rex __ARGS((struct ax25_cb *axp));
  18.  
  19. #define    YES    1
  20. #define    NO    0
  21.  
  22. /* Process incoming frames */
  23. int
  24. lapb_input(axp,cmdrsp,bp)
  25. struct ax25_cb *axp;        /* Link control structure */
  26. char cmdrsp;            /* Command/response flag */
  27. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  28. {
  29.     char control;
  30.     char class;        /* General class (I/S/U) of frame */
  31.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  32.     char pf;        /* extracted poll/final bit */
  33.     char poll = 0;
  34.     char final = 0;
  35.     int nr;            /* ACK number of incoming frame */
  36.     int ns;            /* Seq number of incoming frame */
  37.     char tmp;
  38.  
  39.     if(bp == NULLBUF || axp == NULLAX25){
  40.         free_p(bp);
  41.         return -1;
  42.     }
  43.  
  44.     /* Extract the various parts of the control field for easy use */
  45.     control = pullchar(&bp);
  46.     type = ftype(control);
  47.     class = type & 0x3;
  48.     pf = control & PF;
  49.     /* Check for polls and finals */
  50.     if(pf){
  51.         switch(cmdrsp){
  52.         case COMMAND:
  53.             poll = YES;
  54.             break;
  55.         case RESPONSE:
  56.             final = YES;
  57.             break;
  58.         }
  59.     }
  60.     /* Extract sequence numbers, if present */
  61.     switch(class){
  62.     case I:
  63.     case I+2:
  64.         ns = (control >> 1) & MMASK;
  65.     case S:    /* Note fall-thru */
  66.         nr = (control >> 5) & MMASK;
  67.         break;
  68.     }
  69.     /* This section follows the SDL diagrams by K3NA fairly closely */
  70.     switch(axp->state){
  71.     case DISCONNECTED:
  72.         switch(type){
  73.         case SABM:    /* Initialize or reset link */
  74.             sendctl(axp,RESPONSE,UA|pf);    /* Always accept */
  75.             clr_ex(axp);
  76.             axp->unack = axp->vr = axp->vs = 0;
  77.             lapbstate(axp,CONNECTED);/* Resets state counters */
  78.             axp->srt = Axirtt / MSPTICK;
  79.             axp->t1.start = 2*axp->srt;
  80.             start_timer(&axp->t3);
  81.             break;
  82.         case DM:    /* Ignore to avoid infinite loops */
  83.             break;
  84.         default:    /* All others get DM */
  85.             if(poll)
  86.                 sendctl(axp,RESPONSE,DM|pf);
  87.             break;
  88.         }
  89.         break;
  90.     case SETUP:
  91.         switch(type){
  92.         case SABM:    /* Simultaneous open */
  93.             sendctl(axp,RESPONSE,UA|pf);
  94.             break;
  95.         case DISC:
  96.             sendctl(axp,RESPONSE,DM|pf);
  97.             break;
  98.         case UA:    /* Connection accepted */
  99.             /* Note: xmit queue not cleared */
  100.             stop_timer(&axp->t1);
  101.             start_timer(&axp->t3);
  102.             axp->unack = axp->vr = axp->vs = 0;
  103.             lapbstate(axp,CONNECTED);
  104.             break;            
  105.         case DM:    /* Connection refused */
  106.             free_q(&axp->txq);
  107.             stop_timer(&axp->t1);
  108.             axp->reason = LB_DM;
  109.             lapbstate(axp,DISCONNECTED);
  110.             break;
  111.         default:    /* All other frames ignored */
  112.             break;
  113.         }
  114.         break;
  115.     case DISCPENDING:
  116.         switch(type){
  117.         case SABM:
  118.             sendctl(axp,RESPONSE,DM|pf);
  119.             break;
  120.         case DISC:
  121.             sendctl(axp,RESPONSE,UA|pf);
  122.             break;
  123.         case UA:
  124.         case DM:
  125.             stop_timer(&axp->t1);
  126.             lapbstate(axp,DISCONNECTED);
  127.             break;
  128.         default:    /* Respond with DM only to command polls */
  129.             if(poll)
  130.                 sendctl(axp,RESPONSE,DM|pf);
  131.             break;
  132.         }
  133.         break;
  134.     case CONNECTED:
  135.         switch(type){
  136.         case SABM:
  137.             sendctl(axp,RESPONSE,UA|pf);
  138.             clr_ex(axp);
  139.             free_q(&axp->txq);
  140.             stop_timer(&axp->t1);
  141.             start_timer(&axp->t3);
  142.             axp->unack = axp->vr = axp->vs = 0;
  143.             lapbstate(axp,CONNECTED); /* Purge queues */
  144.             break;
  145.         case DISC:
  146.             free_q(&axp->txq);
  147.             sendctl(axp,RESPONSE,UA|pf);
  148.             stop_timer(&axp->t1);
  149.             stop_timer(&axp->t3);
  150.             axp->reason = LB_NORMAL;
  151.             lapbstate(axp,DISCONNECTED);
  152.             break;
  153.         case DM:
  154.             axp->reason = LB_DM;
  155.             lapbstate(axp,DISCONNECTED);
  156.             break;
  157.         case UA:
  158.             est_link(axp);
  159.             lapbstate(axp,SETUP);    /* Re-establish */    
  160.             break;            
  161.         case FRMR:
  162.             est_link(axp);
  163.             lapbstate(axp,SETUP);    /* Re-establish link */
  164.             break;
  165.         case RR:
  166.         case RNR:
  167.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  168.             if(poll)
  169.                 enq_resp(axp);
  170.             ackours(axp,nr);
  171.             break;
  172.         case REJ:
  173.             axp->flags.remotebusy = NO;
  174.             if(poll)
  175.                 enq_resp(axp);
  176.             ackours(axp,nr);
  177.             stop_timer(&axp->t1);
  178.             start_timer(&axp->t3);
  179.             /* This may or may not actually invoke transmission,
  180.              * depending on whether this REJ was caused by
  181.              * our losing his prior ACK.
  182.              */
  183.             inv_rex(axp);
  184.             break;    
  185.         case I:
  186.             ackours(axp,nr); /** == -1) */
  187.             if(len_mbuf(axp->rxq) >= axp->window){
  188.                 /* Too bad he didn't listen to us; he'll
  189.                  * have to resend the frame later. This
  190.                  * drastic action is necessary to avoid
  191.                  * deadlock.
  192.                  */
  193.                 if(poll)
  194.                     sendctl(axp,RESPONSE,RNR|pf);
  195.                 free_p(bp);
  196.                 bp = NULLBUF;
  197.                 break;
  198.             }
  199.             /* Reject or ignore I-frames with receive sequence number errors */
  200.             if(ns != axp->vr){
  201.                 if(axp->proto == V1 || !axp->flags.rejsent){
  202.                     axp->flags.rejsent = YES;
  203.                     sendctl(axp,RESPONSE,REJ | pf);
  204.                 } else if(poll)
  205.                     enq_resp(axp);
  206.                 axp->response = 0;
  207.                 break;
  208.             }
  209.             axp->flags.rejsent = NO;
  210.             axp->vr = (axp->vr+1) & MMASK;
  211.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  212.             if(poll){
  213.                 sendctl(axp,RESPONSE,tmp|PF);
  214.             } else {
  215.                 axp->response = tmp;
  216.             }
  217.             procdata(axp,bp);
  218.             bp = NULLBUF;
  219.             break;
  220.         default:    /* All others ignored */
  221.             break;
  222.         }
  223.         break;
  224.     case RECOVERY:
  225.         switch(type){
  226.         case SABM:
  227.             sendctl(axp,RESPONSE,UA|pf);
  228.             clr_ex(axp);
  229.             stop_timer(&axp->t1);
  230.             start_timer(&axp->t3);
  231.             axp->unack = axp->vr = axp->vs = 0;
  232.             lapbstate(axp,CONNECTED); /* Purge queues */
  233.             break;
  234.         case DISC:
  235.             free_q(&axp->txq);
  236.             sendctl(axp,RESPONSE,UA|pf);
  237.             stop_timer(&axp->t1);
  238.             stop_timer(&axp->t3);
  239.             axp->response = UA;
  240.             axp->reason = LB_NORMAL;
  241.             lapbstate(axp,DISCONNECTED);
  242.             break;
  243.         case DM:
  244.             axp->reason = LB_DM;
  245.             lapbstate(axp,DISCONNECTED);
  246.             break;
  247.         case UA:
  248.             est_link(axp);
  249.             lapbstate(axp,SETUP);    /* Re-establish */    
  250.             break;
  251.         case FRMR:
  252.             est_link(axp);
  253.             lapbstate(axp,SETUP);    /* Re-establish link */
  254.             break;
  255.         case RR:
  256.         case RNR:
  257.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  258.             if(axp->proto == V1 || final){
  259.                 stop_timer(&axp->t1);
  260.                 ackours(axp,nr);
  261.                 if(axp->unack != 0){
  262.                     inv_rex(axp);
  263.                 } else {
  264.                     start_timer(&axp->t3);
  265.                     lapbstate(axp,CONNECTED);
  266.                 }
  267.             } else {
  268.                 if(poll)
  269.                     enq_resp(axp);
  270.                 ackours(axp,nr);
  271.                 /* Keep timer running even if all frames
  272.                  * were acked, since we must see a Final
  273.                  */
  274.                 if(!run_timer(&axp->t1))
  275.                     start_timer(&axp->t1);
  276.             }
  277.             break;
  278.         case REJ:
  279.             axp->flags.remotebusy = NO;
  280.             /* Don't insist on a Final response from the old proto */
  281.             if(axp->proto == V1 || final){
  282.                 stop_timer(&axp->t1);
  283.                 ackours(axp,nr);
  284.                 if(axp->unack != 0){
  285.                     inv_rex(axp);
  286.                 } else {
  287.                     start_timer(&axp->t3);
  288.                     lapbstate(axp,CONNECTED);
  289.                 }
  290.             } else {
  291.                 if(poll)
  292.                     enq_resp(axp);
  293.                 ackours(axp,nr);
  294.                 if(axp->unack != 0){
  295.                     /* This is certain to trigger output */
  296.                     inv_rex(axp);
  297.                 }
  298.                 /* A REJ that acks everything but doesn't
  299.                  * have the F bit set can cause a deadlock.
  300.                  * So make sure the timer is running.
  301.                  */
  302.                 if(!run_timer(&axp->t1))
  303.                     start_timer(&axp->t1);
  304.             }
  305.             break;
  306.         case I:
  307.             ackours(axp,nr); /** == -1) */
  308.             /* Make sure timer is running, since an I frame
  309.              * cannot satisfy a poll
  310.              */
  311.             if(!run_timer(&axp->t1))
  312.                 start_timer(&axp->t1);
  313.             if(len_mbuf(axp->rxq) >= axp->window){
  314.                 /* Too bad he didn't listen to us; he'll
  315.                  * have to resend the frame later. This
  316.                  * drastic action is necessary to avoid
  317.                  * memory deadlock.
  318.                  */
  319.                 sendctl(axp,RESPONSE,RNR | pf);
  320.                 free_p(bp);
  321.                 bp = NULLBUF;
  322.                 break;
  323.             }
  324.             /* Reject or ignore I-frames with receive sequence number errors */
  325.             if(ns != axp->vr){
  326.                 if(axp->proto == V1 || !axp->flags.rejsent){
  327.                     axp->flags.rejsent = YES;
  328.                     sendctl(axp,RESPONSE,REJ | pf);
  329.                 } else if(poll)
  330.                     enq_resp(axp);
  331.  
  332.                 axp->response = 0;
  333.                 break;
  334.             }
  335.             axp->flags.rejsent = NO;
  336.             axp->vr = (axp->vr+1) & MMASK;
  337.             tmp = len_mbuf(axp->rxq) >= axp->window ? RNR : RR;
  338.             if(poll){
  339.                 sendctl(axp,RESPONSE,tmp|PF);
  340.             } else {
  341.                 axp->response = tmp;
  342.             }
  343.             procdata(axp,bp);
  344.             bp = NULLBUF;
  345.             break;
  346.         default:
  347.             break;        /* Ignored */
  348.         }
  349.         break;
  350.     }
  351.     free_p(bp);    /* In case anything's left */
  352.  
  353.     /* See if we can send some data, perhaps piggybacking an ack.
  354.      * If successful, lapb_output will clear axp->response.
  355.      */
  356.     lapb_output(axp);
  357.     if(axp->response != 0){
  358.         sendctl(axp,RESPONSE,axp->response);
  359.         axp->response = 0;
  360.     }
  361.     return 0;
  362. }
  363. /* Handle incoming acknowledgements for frames we've sent.
  364.  * Free frames being acknowledged.
  365.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  366.  */
  367. static int
  368. ackours(axp,n)
  369. struct ax25_cb *axp;
  370. char n;
  371. {    
  372.     struct mbuf *bp;
  373.     int acked = 0;    /* Count of frames acked by this ACK */
  374.     int oldest;    /* Seq number of oldest unacked I-frame */
  375.  
  376.     /* Free up acknowledged frames by purging frames from the I-frame
  377.      * transmit queue. Start at the remote end's last reported V(r)
  378.      * and keep going until we reach the new sequence number.
  379.      * If we try to free a null pointer,
  380.      * then we have a frame reject condition.
  381.      */
  382.     oldest = (axp->vs - axp->unack) & MMASK;
  383.     while(axp->unack != 0 && oldest != n){
  384.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  385.             /* Acking unsent frame */
  386.             return -1;
  387.         }
  388.         free_p(bp);
  389.         axp->unack--;
  390.         acked++;
  391.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  392.             /* A frame being timed has been acked */
  393.             axp->flags.rtt_run = 0;
  394.             /* Update only if frame wasn't retransmitted */
  395.             if(!axp->flags.retrans)
  396.                 axp->srt = ((axp->srt * 7) +
  397.                  (Clock - axp->rtt_time)) >> 3;
  398.         }
  399.         axp->flags.retrans = 0;
  400.         axp->retries = 0;
  401.         oldest = (oldest + 1) & MMASK;
  402.     }
  403.     if(axp->unack == 0){
  404.         /* All frames acked, stop timeout */
  405.         stop_timer(&axp->t1);
  406.         start_timer(&axp->t3);
  407.     } else if(acked != 0) { 
  408.         /* Partial ACK; restart timer */
  409.         start_timer(&axp->t1);
  410.     }
  411.     if(acked != 0){
  412.         /* If user has set a transmit upcall, indicate how many frames
  413.          * may be queued
  414.          */
  415.         if(axp->t_upcall != NULLVFP)
  416.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  417.     }
  418.     return 0;
  419. }
  420.  
  421. /* Establish data link */
  422. void
  423. est_link(axp)
  424. struct ax25_cb *axp;
  425. {
  426.     clr_ex(axp);
  427.     axp->retries = 0;
  428.     sendctl(axp,COMMAND,SABM|PF);
  429.     stop_timer(&axp->t3);
  430.     start_timer(&axp->t1);
  431. }
  432. /* Clear exception conditions */
  433. static void
  434. clr_ex(axp)
  435. struct ax25_cb *axp;
  436. {
  437.     axp->flags.remotebusy = NO;
  438.     axp->flags.rejsent = NO;
  439.     axp->response = 0;
  440.     stop_timer(&axp->t3);
  441. }
  442. /* Enquiry response */
  443. static void
  444. enq_resp(axp)
  445. struct ax25_cb *axp;
  446. {
  447.     char ctl;
  448.  
  449.     ctl = len_mbuf(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  450.     sendctl(axp,RESPONSE,ctl);
  451.     axp->response = 0;
  452.     stop_timer(&axp->t3);
  453. }
  454. /* Invoke retransmission */
  455. static void
  456. inv_rex(axp)
  457. struct ax25_cb *axp;
  458. {
  459.     axp->vs -= axp->unack;
  460.     axp->vs &= MMASK;
  461.     axp->unack = 0;
  462. }
  463. /* Send S or U frame to currently connected station */
  464. int
  465. sendctl(axp,cmdrsp,cmd)
  466. struct ax25_cb *axp;
  467. char cmdrsp,cmd;
  468. {
  469.     if((ftype(cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  470.         cmd |= (axp->vr << 5);
  471.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  472. }
  473. /* Start data transmission on link, if possible
  474.  * Return number of frames sent
  475.  */
  476. int
  477. lapb_output(axp)
  478. register struct ax25_cb *axp;
  479. {
  480.     register struct mbuf *bp;
  481.     struct mbuf *tbp;
  482.     char control;
  483.     int sent = 0;
  484.     int i;
  485.  
  486.     if(axp == NULLAX25
  487.      || (axp->state != RECOVERY && axp->state != CONNECTED)
  488.      || axp->flags.remotebusy)
  489.         return 0;
  490.  
  491.     /* Dig into the send queue for the first unsent frame */
  492.     bp = axp->txq;
  493.     for(i = 0; i < axp->unack; i++){
  494.         if(bp == NULLBUF)
  495.             break;    /* Nothing to do */
  496.         bp = bp->anext;
  497.     }
  498.     /* Start at first unsent I-frame, stop when either the
  499.      * number of unacknowledged frames reaches the maxframe limit,
  500.      * or when there are no more frames to send
  501.      */
  502.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  503.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  504.         axp->vs &= MMASK;
  505.         dup_p(&tbp,bp,0,len_mbuf(bp));
  506.         if(tbp == NULLBUF)
  507.             return sent;    /* Probably out of memory */
  508.         sendframe(axp,COMMAND,control,tbp);
  509.         axp->unack++;
  510.         /* We're implicitly acking any data he's sent, so stop any
  511.          * delayed ack
  512.          */
  513.         axp->response = 0;
  514.         /* Use clamped backoff algorithm */
  515.         if(!axp->flags.retrans)
  516.             axp->t1.start = 2 * (axp->srt << axp->retries);
  517.         if(!run_timer(&axp->t1)){
  518.             stop_timer(&axp->t3);
  519.             start_timer(&axp->t1);
  520.         }
  521.         sent++;
  522.         bp = bp->anext;
  523.         if(!axp->flags.rtt_run){
  524.             /* Start round trip timer */
  525.             axp->rtt_seq = (control >> 1) & MMASK;
  526.             axp->rtt_time = Clock;
  527.             axp->flags.rtt_run = 1;
  528.         }
  529.     }
  530.     return sent;
  531. }
  532. /* Set new link state */
  533. void
  534. lapbstate(axp,s)
  535. struct ax25_cb *axp;
  536. int s;
  537. {
  538.     int oldstate;
  539.  
  540.     oldstate = axp->state;
  541.     axp->state = s;
  542.     if(s == DISCONNECTED){
  543.         stop_timer(&axp->t1);
  544.         stop_timer(&axp->t3);
  545.         free_q(&axp->txq);
  546.     }
  547.     /* Don't bother the client unless the state is really changing */
  548.     if(oldstate != s && axp->s_upcall != NULLVFP)
  549.         (*axp->s_upcall)(axp,oldstate,s);
  550. }
  551. /* Process a valid incoming I frame */
  552. static void
  553. procdata(axp,bp)
  554. struct ax25_cb *axp;
  555. struct mbuf *bp;
  556. {
  557.     char pid;
  558.     char seq;
  559.  
  560.     /* Extract level 3 PID */
  561.     if(pullup(&bp,&pid,1) != 1)
  562.         return;    /* No PID */
  563.  
  564.     if(axp->segremain != 0){
  565.         /* Reassembly in progress; continue */
  566.         pullup(&bp,&seq,1);
  567.         if(uchar(pid) == PID_SEGMENT
  568.          && (seq & SEG_REM) == axp->segremain - 1){
  569.             /* Correct, in-order segment */
  570.             append(&axp->rxasm,bp);
  571.             if((axp->segremain = (seq & SEG_REM)) == 0){
  572.                 /* Done; kick it upstairs */
  573.                 bp = axp->rxasm;
  574.                 axp->rxasm = NULLBUF;
  575.                 pullup(&bp,&pid,1);
  576.                 handleit(axp,pid,bp);
  577.             }
  578.         } else {
  579.             /* Error! */
  580.             free_p(axp->rxasm);
  581.             axp->rxasm = NULLBUF;
  582.             axp->segremain = 0;
  583.             free_p(bp);
  584.         }
  585.     } else {
  586.         /* No reassembly in progress */
  587.         if(uchar(pid) == PID_SEGMENT){
  588.             /* Start reassembly */
  589.             pullup(&bp,&seq,1);
  590.             if(!(seq & SEG_FIRST)){
  591.                 free_p(bp);    /* not first seg - error! */
  592.             } else {
  593.                 /* Put first segment on list */
  594.                 axp->segremain = seq & SEG_REM;
  595.                 axp->rxasm = bp;
  596.             }
  597.         } else {
  598.             /* Normal frame; send upstairs */
  599.             handleit(axp,pid,bp);
  600.         }
  601.     }
  602. }
  603. /* New-style frame segmenter. Returns queue of segmented fragments, or
  604.  * original packet if small enough
  605.  */
  606. struct mbuf *
  607. segmenter(bp,ssize)
  608. struct mbuf *bp;    /* Complete packet */
  609. int16 ssize;        /* Max size of frame segments */
  610. {
  611.     struct mbuf *result = NULLBUF;
  612.     struct mbuf *bptmp,*bp1;
  613.     int16 len,offset;
  614.     int segments;
  615.  
  616.     /* See if packet is too small to segment. Note 1-byte grace factor
  617.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  618.      */
  619.     len = len_mbuf(bp);
  620.     if(len <= ssize+1)
  621.         return bp;    /* Too small to segment */
  622.  
  623.     ssize -= 2;        /* ssize now equal to data portion size */
  624.     segments = 1 + (len - 1) / ssize;    /* # segments  */
  625.     offset = 0;
  626.  
  627.     while(segments != 0){
  628.         offset += dup_p(&bptmp,bp,offset,ssize);
  629.         if(bptmp == NULLBUF){
  630.             free_q(&result);
  631.             break;
  632.         }
  633.         /* Make room for segmentation header */
  634.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  635.             free_p(bptmp);
  636.             free_q(&result);
  637.             break;
  638.         }
  639.         bp1->data[0] = PID_SEGMENT;
  640.         bp1->data[1] = --segments;
  641.         if(offset == ssize)
  642.             bp1->data[1] |= SEG_FIRST;
  643.         enqueue(&result,bp1);
  644.     }
  645.     free_p(bp);
  646.     return result;
  647. }
  648.  
  649. static void
  650. handleit(axp,pid,bp)
  651. struct ax25_cb *axp;
  652. char pid;
  653. struct mbuf *bp;
  654. {
  655.     switch(uchar(pid)){
  656.     case PID_IP:        /* DoD Internet Protocol */
  657.         ip_route(axp->iface,bp,0);
  658.         break;
  659.     case PID_NO_L3:        /* Enqueue for application */
  660.         append(&axp->rxq,bp);
  661.         if(axp->r_upcall != NULLVFP)
  662.             (*axp->r_upcall)(axp,len_mbuf(axp->rxq));
  663.         break;    
  664.     case PID_NETROM:
  665.         nr_route(bp,axp);
  666.         break;
  667.     default:        /* Note: ARP is invalid here */    
  668.         free_p(bp);
  669.         break;            
  670.     }
  671. }
  672.  
  673.